<template>
  <div class="container" ref="container"></div>
</template>
<script setup>
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import { RGBELoader } from "three/examples/jsm/loaders/RGBELoader";
import { ref, onMounted } from "vue";
import gsap from "gsap";

let progress = ref(0);
// 初始化场景
const scene = new THREE.Scene();
//初始化相机
const camera = new THREE.PerspectiveCamera(
  75,
  window.innerWidth / window.innerHeight,
  0.1,
  1000
);
//初始化相机位置 (房间中从原点进行查看)
camera.position.set(0, 0, 0);
//初始化渲染器
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);

//添加辅助坐标系
// const axes = new THREE.AxesHelper();
// scene.add(axes);
const container = ref(null);

const render = () => {
  //渲染场景
  renderer.render(scene, camera);
  //渲染动画
  requestAnimationFrame(render);
};
//组件挂载完成后渲染
onMounted(() => {
  //将渲染后的canvas 添加到dom中
  container.value.appendChild(renderer.domElement);
  render();

  //监听鼠标事件
  let isMouseDown = false;
  container.value.addEventListener("mousedown", () => {
    isMouseDown = true;
  });
  container.value.addEventListener("mouseup", () => {
    isMouseDown = false;
  });
  container.value.addEventListener("mouseout", () => {
    isMouseDown = false;
  });
  container.value.addEventListener("mousemove", (event) => {
    if (isMouseDown) {
      camera.rotation.y += event.movementX * 0.002;
      camera.rotation.x += event.movementY * 0.002;
      //旋转顺序 默认是XYZ
      camera.rotation.order = "YXZ";
      console.log(camera.position)
    }
  });
  //初始化房间
  //客厅
  let livingRoom = new Room("客厅", 0, "./images/livingroom/");
  //厨房
  let kitchen = new Room(
    "厨房",
    3,
    "./images/kitchen/",
    new THREE.Vector3(-5, 0, -10),
    new THREE.Euler(0, -Math.PI / 2, 0)
  );
  //阳台
  let balcony = new Room(
    "阳台",
    8,
    "./images/balcony/",
    new THREE.Vector3(0, 0, 10)
  );

  //厨房文字->客厅
  let livingText = new SpriteText("客厅", new THREE.Vector3(-5, 0, -6));
  livingText.onClick(() => {
    // 让相机移动到客厅
    console.log("跳转至客厅");
    gsap.to(camera.position, {
      duration: 1,
      x: livingRoom.position.x,
      y: livingRoom.position.y,
      z: livingRoom.position.z,
    });
  });
  //阳台->客厅
  let livingText1 = new SpriteText("客厅", new THREE.Vector3(-1.2, 0, 6));
  livingText1.onClick(() => {
    // 让相机移动到客厅
    console.log("跳转至客厅");
    gsap.to(camera.position, {
      duration: 1,
      x: livingRoom.position.x,
      y: livingRoom.position.y,
      z: livingRoom.position.z,
    });
  });
  //客厅->厨房
  let kitchenText = new SpriteText("厨房", new THREE.Vector3(-1.8, 0, -4));
  kitchenText.onClick(() => {
    // 让相机移动到厨房
    console.log("跳转至厨房");
    gsap.to(camera.position, {
      duration: 1,
      x: kitchen.position.x,
      y: kitchen.position.y,
      z: kitchen.position.z,
    });
  });

  let balconyText = new SpriteText("阳台", new THREE.Vector3(0, 0, 4));
  balconyText.onClick(() => {
    // 让相机移动到阳台
    console.log("跳转至阳台");
    gsap.to(camera.position, {
      duration: 1,
      x: balcony.position.x,
      y: balcony.position.y,
      z: balcony.position.z,
    });
  });
});

class Room {
  constructor(
    name,
    roomIndex,
    textureUrl,
    position = new THREE.Vector3(0, 0, 0),
    euler = new THREE.Euler(0, 0, 0)
  ) {
    this.name = name;
    this.position = position;
    //创建一个立方体
    const geometry = new THREE.BoxGeometry(10, 10, 10);
    //-1 反过来
    geometry.scale(1, 1, -1);

    //纹理图片路径
    var arr = [
      `${roomIndex}_l`, //左
      `${roomIndex}_r`, //右
      `${roomIndex}_u`, //上
      `${roomIndex}_d`, //下
      `${roomIndex}_b`, //后
      `${roomIndex}_f`, //前
    ];
    let boxMaterials = [];
    arr.forEach((item) => {
      const texture = new THREE.TextureLoader().load(
        textureUrl + item + ".jpg"
      );
      if (item === `${roomIndex}_d` || item === `${roomIndex}_u`) {
        texture.rotation = Math.PI;
        texture.center = new THREE.Vector2(0.5, 0.5);
      }
      boxMaterials.push(new THREE.MeshBasicMaterial({ map: texture }));
    });
    const cube = new THREE.Mesh(geometry, boxMaterials);
    cube.position.copy(position);
    cube.rotation.copy(euler);
    scene.add(cube);
  }
}

class SpriteText {
  constructor(text, position) {
    this.callbacks = [];
    const canvas = document.createElement("canvas");
    canvas.width = 1024;
    canvas.height = 1024;
    const context = canvas.getContext("2d");
    context.fillStyle = "rgba(100, 100, 100, 0.7)";
    context.fillRect(0, 256, 1024, 512);
    context.textAlign = "center";
    context.textBaseline = "middle";
    context.font = "bold 200px Arial";
    context.fillStyle = "white";
    context.fillText(text, 512, 512);
    let texture = new THREE.CanvasTexture(canvas);

    const material = new THREE.SpriteMaterial({
      map: texture,
      transparent: true,
      depthWrite: true,
    });
    const sprite = new THREE.Sprite(material);
    sprite.scale.set(0.6, 0.6, 0.6);
    sprite.position.copy(position);
    this.sprite = sprite;
    sprite.renderOrder = 1;
    scene.add(sprite);
    let mouse = new THREE.Vector2();
    let raycaster = new THREE.Raycaster();
    window.addEventListener("click", (event) => {
      mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
      mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
      raycaster.setFromCamera(mouse, camera);
      let intersects = raycaster.intersectObject(sprite);
      if (intersects.length > 0) {
        this.callbacks.forEach((callback) => {
          callback();
        });
      }
    });
  }
  onClick(callback) {
    this.callbacks.push(callback);
  }
}
</script>

<style>
* {
  margin: 0;
  padding: 0;
}
.container {
  height: 100vh;
  width: 100vw;
  background-color: #f0f0f0;
}
</style>
